//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_board_api_serv

import (
	"context"

	"atomgit.com/openlinksaas/api-server/api_common"
	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/project_board_dao"
	"atomgit.com/openlinksaas/api-server/dao/project_entry_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/notices/notices_board"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_board_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *ProjectBoardApiImpl) CreateNode(ctx context.Context, req *project_board_api.CreateNodeRequest) (*project_board_api.CreateNodeResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_board_api.CreateNodeResponse{
			Code:   project_board_api.CreateNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_board_api.CreateNodeResponse{
			Code:   project_board_api.CreateNodeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_board_api.CreateNodeResponse{
			Code:   project_board_api.CreateNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.BoardId, req.ProjectId)
	if err != nil {
		return &project_board_api.CreateNodeResponse{
			Code:   project_board_api.CreateNodeResponse_CODE_NO_BOARD,
			ErrMsg: "信息面板不存在",
		}, nil
	}
	canUpdate := api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)
	if !canUpdate {
		return &project_board_api.CreateNodeResponse{
			Code:   project_board_api.CreateNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nodeId := uuid.NewString()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		dbItem := &project_board_dao.NodeDbItem{
			NodeId:    nodeId,
			BoardId:   req.BoardId,
			ProjectId: req.ProjectId,
			NodeType:  uint32(req.NodeType),
			X:         req.X,
			Y:         req.Y,
			W:         req.W,
			H:         req.H,
			BgColor:   "white",
		}
		if req.NodeType == project_board_api.NODE_TYPE_NODE_TYPE_REF {
			extraData := req.NodeData.(*project_board_api.CreateNodeRequest_NodeRefData)
			dbItem.NodeRefData = &project_board_dao.NodeRefDataDbItem{
				RefType:     uint32(extraData.NodeRefData.RefType),
				RefTargetId: extraData.NodeRefData.RefTargetId,
			}
		} else if req.NodeType == project_board_api.NODE_TYPE_NODE_TYPE_TEXT {
			extraData := req.NodeData.(*project_board_api.CreateNodeRequest_NodeTextData)
			dbItem.NodeTextData = &project_board_dao.NodeTextDataDbItem{
				Data: extraData.NodeTextData.Data,
			}
		} else if req.NodeType == project_board_api.NODE_TYPE_NODE_TYPE_IMAGE {
			extraData := req.NodeData.(*project_board_api.CreateNodeRequest_NodeImageData)
			dbItem.NodeImageData = &project_board_dao.NodeImageDataDbItem{
				FileId: extraData.NodeImageData.FileId,
			}
		} else if req.NodeType == project_board_api.NODE_TYPE_NODE_TYPE_MERMAID {
			extraData := req.NodeData.(*project_board_api.CreateNodeRequest_NodeMermaidData)
			dbItem.NodeMermaidData = &project_board_dao.NodeMermaidDataDbItem{
				Data: extraData.NodeMermaidData.Data,
			}
		}
		err = project_board_dao.NodeDao.Insert(sessCtx, dbItem)
		if err != nil {
			return nil, err
		}
		return &project_board_api.CreateNodeResponse{
			Code:   project_board_api.CreateNodeResponse_CODE_OK,
			NodeId: nodeId,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_board.CreateNodeNotice{
		ProjectId: req.ProjectId,
		BoardId:   req.BoardId,
		NodeId:    nodeId,
	})
	return ret.(*project_board_api.CreateNodeResponse), nil
}

func (apiImpl *ProjectBoardApiImpl) UpdateNodePosition(ctx context.Context, req *project_board_api.UpdateNodePositionRequest) (*project_board_api.UpdateNodePositionResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_board_api.UpdateNodePositionResponse{
			Code:   project_board_api.UpdateNodePositionResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_board_api.UpdateNodePositionResponse{
			Code:   project_board_api.UpdateNodePositionResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_board_api.UpdateNodePositionResponse{
			Code:   project_board_api.UpdateNodePositionResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.BoardId, req.ProjectId)
	if err != nil {
		return &project_board_api.UpdateNodePositionResponse{
			Code:   project_board_api.UpdateNodePositionResponse_CODE_NO_BOARD,
			ErrMsg: "信息面板不存在",
		}, nil
	}
	canUpdate := api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)
	if !canUpdate {
		return &project_board_api.UpdateNodePositionResponse{
			Code:   project_board_api.UpdateNodePositionResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	exist, err := project_board_dao.NodeDao.Exist(ctx, req.ProjectId, req.BoardId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_board_api.UpdateNodePositionResponse{
			Code:   project_board_api.UpdateNodePositionResponse_CODE_NO_NODE,
			ErrMsg: "节点不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_board_dao.NodeDao.UpdatePosition(sessCtx, req.ProjectId, req.BoardId, req.NodeId, req.X, req.Y)
		if err != nil {
			return nil, err
		}
		return &project_board_api.UpdateNodePositionResponse{
			Code: project_board_api.UpdateNodePositionResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_board.UpdateNodeNotice{
		ProjectId: req.ProjectId,
		BoardId:   req.BoardId,
		NodeId:    req.NodeId,
	})
	return ret.(*project_board_api.UpdateNodePositionResponse), nil
}

func (apiImpl *ProjectBoardApiImpl) UpdateNodeSize(ctx context.Context, req *project_board_api.UpdateNodeSizeRequest) (*project_board_api.UpdateNodeSizeResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_board_api.UpdateNodeSizeResponse{
			Code:   project_board_api.UpdateNodeSizeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_board_api.UpdateNodeSizeResponse{
			Code:   project_board_api.UpdateNodeSizeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_board_api.UpdateNodeSizeResponse{
			Code:   project_board_api.UpdateNodeSizeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.BoardId, req.ProjectId)
	if err != nil {
		return &project_board_api.UpdateNodeSizeResponse{
			Code:   project_board_api.UpdateNodeSizeResponse_CODE_NO_BOARD,
			ErrMsg: "信息面板不存在",
		}, nil
	}
	canUpdate := api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)
	if !canUpdate {
		return &project_board_api.UpdateNodeSizeResponse{
			Code:   project_board_api.UpdateNodeSizeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	exist, err := project_board_dao.NodeDao.Exist(ctx, req.ProjectId, req.BoardId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_board_api.UpdateNodeSizeResponse{
			Code:   project_board_api.UpdateNodeSizeResponse_CODE_NO_NODE,
			ErrMsg: "节点不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_board_dao.NodeDao.UpdateSize(sessCtx, req.ProjectId, req.BoardId, req.NodeId, req.W, req.H)
		if err != nil {
			return nil, err
		}
		return &project_board_api.UpdateNodeSizeResponse{
			Code: project_board_api.UpdateNodeSizeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_board.UpdateNodeNotice{
		ProjectId: req.ProjectId,
		BoardId:   req.BoardId,
		NodeId:    req.NodeId,
	})
	return ret.(*project_board_api.UpdateNodeSizeResponse), nil
}

func (apiImpl *ProjectBoardApiImpl) UpdateNodeBgColor(ctx context.Context, req *project_board_api.UpdateNodeBgColorRequest) (*project_board_api.UpdateNodeBgColorResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_board_api.UpdateNodeBgColorResponse{
			Code:   project_board_api.UpdateNodeBgColorResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_board_api.UpdateNodeBgColorResponse{
			Code:   project_board_api.UpdateNodeBgColorResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_board_api.UpdateNodeBgColorResponse{
			Code:   project_board_api.UpdateNodeBgColorResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.BoardId, req.ProjectId)
	if err != nil {
		return &project_board_api.UpdateNodeBgColorResponse{
			Code:   project_board_api.UpdateNodeBgColorResponse_CODE_NO_BOARD,
			ErrMsg: "信息面板不存在",
		}, nil
	}
	canUpdate := api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)
	if !canUpdate {
		return &project_board_api.UpdateNodeBgColorResponse{
			Code:   project_board_api.UpdateNodeBgColorResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	exist, err := project_board_dao.NodeDao.Exist(ctx, req.ProjectId, req.BoardId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_board_api.UpdateNodeBgColorResponse{
			Code:   project_board_api.UpdateNodeBgColorResponse_CODE_NO_NODE,
			ErrMsg: "节点不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_board_dao.NodeDao.UpdateBgColor(sessCtx, req.ProjectId, req.BoardId, req.NodeId, req.BgColor)
		if err != nil {
			return nil, err
		}
		return &project_board_api.UpdateNodeBgColorResponse{
			Code: project_board_api.UpdateNodeBgColorResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_board.UpdateNodeNotice{
		ProjectId: req.ProjectId,
		BoardId:   req.BoardId,
		NodeId:    req.NodeId,
	})
	return ret.(*project_board_api.UpdateNodeBgColorResponse), nil
}

func (apiImpl *ProjectBoardApiImpl) StartUpdateContent(ctx context.Context, req *project_board_api.StartUpdateContentRequest) (*project_board_api.StartUpdateContentResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_board_api.StartUpdateContentResponse{
			Code:   project_board_api.StartUpdateContentResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_board_api.StartUpdateContentResponse{
			Code:   project_board_api.StartUpdateContentResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_board_api.StartUpdateContentResponse{
			Code:   project_board_api.StartUpdateContentResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.BoardId, req.ProjectId)
	if err != nil {
		return &project_board_api.StartUpdateContentResponse{
			Code:   project_board_api.StartUpdateContentResponse_CODE_NO_BOARD,
			ErrMsg: "信息面板不存在",
		}, nil
	}
	canUpdate := api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)
	if !canUpdate {
		return &project_board_api.StartUpdateContentResponse{
			Code:   project_board_api.StartUpdateContentResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	exist, err := project_board_dao.NodeDao.Exist(ctx, req.ProjectId, req.BoardId, req.NodeId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_board_api.StartUpdateContentResponse{
			Code:   project_board_api.StartUpdateContentResponse_CODE_NO_NODE,
			ErrMsg: "节点不存在",
		}, nil
	}
	//检查编辑状态
	editItem, ok := dao.CacheDao.GetBoardNodeEdit(ctx, req.NodeId)
	if ok && editItem.EditUserId != sessionItem.UserId {
		return &project_board_api.StartUpdateContentResponse{
			Code:   project_board_api.StartUpdateContentResponse_CODE_IN_EDIT,
			ErrMsg: "节点处于编辑状态",
		}, nil
	}

	err = dao.CacheDao.SetBoardNodeEdit(ctx, &dao.BoardNodeEditDbItem{
		ProjectId:  req.ProjectId,
		BoardId:    req.BoardId,
		NodeId:     req.NodeId,
		EditUserId: sessionItem.UserId,
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_board.UpdateNodeNotice{
		ProjectId: req.ProjectId,
		BoardId:   req.BoardId,
		NodeId:    req.NodeId,
	})
	return &project_board_api.StartUpdateContentResponse{
		Code: project_board_api.StartUpdateContentResponse_CODE_OK,
	}, nil
}

func (apiImpl *ProjectBoardApiImpl) KeepUpdateContent(ctx context.Context, req *project_board_api.KeepUpdateContentRequest) (*project_board_api.KeepUpdateContentResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_board_api.KeepUpdateContentResponse{
			Code:   project_board_api.KeepUpdateContentResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	editItem, ok := dao.CacheDao.GetBoardNodeEdit(ctx, req.NodeId)
	if !ok {
		return &project_board_api.KeepUpdateContentResponse{
			Code:   project_board_api.KeepUpdateContentResponse_CODE_NOT_IN_EDIT,
			ErrMsg: "节点处于非编辑状态",
		}, nil
	}
	if editItem.EditUserId != sessionItem.UserId {
		return &project_board_api.KeepUpdateContentResponse{
			Code:   project_board_api.KeepUpdateContentResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有更新权限",
		}, nil
	}
	dao.CacheDao.KeepBoardNodeEdit(ctx, req.NodeId)

	return &project_board_api.KeepUpdateContentResponse{
		Code: project_board_api.KeepUpdateContentResponse_CODE_OK,
	}, nil
}

func (apiImpl *ProjectBoardApiImpl) EndUpdateContent(ctx context.Context, req *project_board_api.EndUpdateContentRequest) (*project_board_api.EndUpdateContentResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_board_api.EndUpdateContentResponse{
			Code:   project_board_api.EndUpdateContentResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	editItem, ok := dao.CacheDao.GetBoardNodeEdit(ctx, req.NodeId)
	if !ok {
		return &project_board_api.EndUpdateContentResponse{
			Code: project_board_api.EndUpdateContentResponse_CODE_OK,
		}, nil
	}
	if editItem.EditUserId != sessionItem.UserId {
		return &project_board_api.EndUpdateContentResponse{
			Code:   project_board_api.EndUpdateContentResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有更新权限",
		}, nil
	}

	dao.CacheDao.RemoveBoardNodeEdit(ctx, req.NodeId)
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_board.UpdateNodeNotice{
		ProjectId: req.ProjectId,
		BoardId:   req.BoardId,
		NodeId:    req.NodeId,
	})
	return &project_board_api.EndUpdateContentResponse{
		Code: project_board_api.EndUpdateContentResponse_CODE_OK,
	}, nil
}

func (apiImpl *ProjectBoardApiImpl) UpdateContent(ctx context.Context, req *project_board_api.UpdateContentRequest) (*project_board_api.UpdateContentResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_board_api.UpdateContentResponse{
			Code:   project_board_api.UpdateContentResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_board_api.UpdateContentResponse{
			Code:   project_board_api.UpdateContentResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_board_api.UpdateContentResponse{
			Code:   project_board_api.UpdateContentResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}

	editItem, ok := dao.CacheDao.GetBoardNodeEdit(ctx, req.NodeId)
	if !ok {
		return &project_board_api.UpdateContentResponse{
			Code:   project_board_api.UpdateContentResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if editItem.EditUserId != sessionItem.UserId {
		return &project_board_api.UpdateContentResponse{
			Code:   project_board_api.UpdateContentResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nodeItem, err := project_board_dao.NodeDao.Get(ctx, req.ProjectId, req.BoardId, req.NodeId)
	if err != nil {
		return &project_board_api.UpdateContentResponse{
			Code:   project_board_api.UpdateContentResponse_CODE_NO_NODE,
			ErrMsg: "节点不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		if nodeItem.NodeType == uint32(project_board_api.NODE_TYPE_NODE_TYPE_REF) {
			nodeData := req.NodeData.(*project_board_api.UpdateContentRequest_NodeRefData)
			err = project_board_dao.NodeDao.UpdateNodeRefData(sessCtx, req.ProjectId, req.BoardId, req.NodeId,
				&project_board_dao.NodeRefDataDbItem{
					RefType:     uint32(nodeData.NodeRefData.RefType),
					RefTargetId: nodeData.NodeRefData.RefTargetId,
				})
			if err != nil {
				return nil, err
			}
		} else if nodeItem.NodeType == uint32(project_board_api.NODE_TYPE_NODE_TYPE_TEXT) {
			nodeData := req.NodeData.(*project_board_api.UpdateContentRequest_NodeTextData)
			err = project_board_dao.NodeDao.UpdateNodeTextData(sessCtx, req.ProjectId, req.BoardId, req.NodeId,
				&project_board_dao.NodeTextDataDbItem{
					Data: nodeData.NodeTextData.Data,
				})
			if err != nil {
				return nil, err
			}
		} else if nodeItem.NodeType == uint32(project_board_api.NODE_TYPE_NODE_TYPE_IMAGE) {
			nodeData := req.NodeData.(*project_board_api.UpdateContentRequest_NodeImageData)
			err = project_board_dao.NodeDao.UpdateNodeImageData(sessCtx, req.ProjectId, req.BoardId, req.NodeId,
				&project_board_dao.NodeImageDataDbItem{
					FileId: nodeData.NodeImageData.FileId,
				})
			if err != nil {
				return nil, err
			}
		} else if nodeItem.NodeType == uint32(project_board_api.NODE_TYPE_NODE_TYPE_MERMAID) {
			nodeData := req.NodeData.(*project_board_api.UpdateContentRequest_NodeMermaidData)
			err = project_board_dao.NodeDao.UpdateNodeMermaidData(sessCtx, req.ProjectId, req.BoardId, req.NodeId,
				&project_board_dao.NodeMermaidDataDbItem{
					Data: nodeData.NodeMermaidData.Data,
				})
		}
		return &project_board_api.UpdateContentResponse{
			Code: project_board_api.UpdateContentResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*project_board_api.UpdateContentResponse), nil
}

func (apiImpl *ProjectBoardApiImpl) RemoveNode(ctx context.Context, req *project_board_api.RemoveNodeRequest) (*project_board_api.RemoveNodeResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_board_api.RemoveNodeResponse{
			Code:   project_board_api.RemoveNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_board_api.RemoveNodeResponse{
			Code:   project_board_api.RemoveNodeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_board_api.RemoveNodeResponse{
			Code:   project_board_api.RemoveNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.BoardId, req.ProjectId)
	if err != nil {
		return &project_board_api.RemoveNodeResponse{
			Code:   project_board_api.RemoveNodeResponse_CODE_NO_BOARD,
			ErrMsg: "信息面板不存在",
		}, nil
	}
	canUpdate := api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)
	if !canUpdate {
		return &project_board_api.RemoveNodeResponse{
			Code:   project_board_api.RemoveNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	exist, err := dao.CacheDao.ExistBoardNodeEdit(ctx, req.NodeId)
	if err != nil {
		return nil, err
	}
	if exist {
		return &project_board_api.RemoveNodeResponse{
			Code:   project_board_api.RemoveNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_board_dao.NodeDao.Remove(sessCtx, req.ProjectId, req.BoardId, req.NodeId)
		if err != nil {
			return nil, err
		}
		//删除相关的边
		err = project_board_dao.EdgeDao.RemoveByFromNode(sessCtx, req.BoardId, req.NodeId)
		if err != nil {
			return nil, err
		}
		err = project_board_dao.EdgeDao.RemoveByToNode(sessCtx, req.BoardId, req.NodeId)
		if err != nil {
			return nil, err
		}
		return &project_board_api.RemoveNodeResponse{
			Code: project_board_api.RemoveNodeResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go api_common.SendNoticeToProjectScope(context.Background(), req.ProjectId, &notices_board.RemoveNodeNotice{
		ProjectId: req.ProjectId,
		BoardId:   req.BoardId,
		NodeId:    req.NodeId,
	})
	return ret.(*project_board_api.RemoveNodeResponse), nil
}

func (apiImpl *ProjectBoardApiImpl) ListNode(ctx context.Context, req *project_board_api.ListNodeRequest) (*project_board_api.ListNodeResponse, error) {
	emptyList := []*project_board_api.Node{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_board_api.ListNodeResponse{
			Code:     project_board_api.ListNodeResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			NodeList: emptyList,
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_board_api.ListNodeResponse{
			Code:     project_board_api.ListNodeResponse_CODE_NO_PROJECT,
			ErrMsg:   "项目不存在",
			NodeList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_board_api.ListNodeResponse{
			Code:     project_board_api.ListNodeResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			NodeList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	nodeItemList, err := project_board_dao.NodeDao.List(ctx, req.ProjectId, req.BoardId)
	if err != nil {
		return nil, err
	}
	//生成结果
	nodeList := []*project_board_api.Node{}
	for _, nodeItem := range nodeItemList {
		node := nodeItem.ToNode()
		exist, _ := dao.CacheDao.ExistBoardNodeEdit(ctx, nodeItem.NodeId) //skip error check
		node.InEdit = exist
		nodeList = append(nodeList, node)
	}

	return &project_board_api.ListNodeResponse{
		Code:     project_board_api.ListNodeResponse_CODE_OK,
		NodeList: nodeList,
	}, nil
}

func (apiImpl *ProjectBoardApiImpl) GetNode(ctx context.Context, req *project_board_api.GetNodeRequest) (*project_board_api.GetNodeResponse, error) {
	emptyNode := &project_board_api.Node{
		NodeData: &project_board_api.Node_NodeRefData{
			NodeRefData: &project_board_api.NodeRefData{},
		},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_board_api.GetNodeResponse{
			Code:   project_board_api.GetNodeResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Node:   emptyNode,
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_board_api.GetNodeResponse{
			Code:   project_board_api.GetNodeResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
			Node:   emptyNode,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_board_api.GetNodeResponse{
			Code:   project_board_api.GetNodeResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Node:   emptyNode,
		}, nil
	} else if err != nil {
		return nil, err
	}

	nodeItem, err := project_board_dao.NodeDao.Get(ctx, req.ProjectId, req.BoardId, req.NodeId)
	if err != nil {
		return &project_board_api.GetNodeResponse{
			Code:   project_board_api.GetNodeResponse_CODE_NO_NODE,
			ErrMsg: "节点不存在",
			Node:   emptyNode,
		}, nil
	}

	//生成结果
	node := nodeItem.ToNode()
	exist, _ := dao.CacheDao.ExistBoardNodeEdit(ctx, req.NodeId)
	node.InEdit = exist
	return &project_board_api.GetNodeResponse{
		Code: project_board_api.GetNodeResponse_CODE_OK,
		Node: node,
	}, nil
}
